﻿using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Installer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;

namespace MRSite.Common.Dependency
{
    public class ContainerManager : IContainerManager
    {
        private static readonly Lazy<ContainerManager> lazy = new Lazy<ContainerManager>(() => new ContainerManager());

        public static ContainerManager Instance { get { return lazy.Value; } }

        public IWindsorContainer Container { get; private set; }

        public ContainerManager()
        {
            Container = new WindsorContainer();
            _registList = new List<IBasicRegister>();
            Container.Register(
                Component.For<ContainerManager,
                    IContainerManager,
                    IContainerRegister,
                    IContainerResolver>().UsingFactoryMethod(() => this).LifestyleSingleton()
                );
            //Container = Builder.Build();
        }

        public void AddRegister(IBasicRegister basicRegister)
        {
            _registList.Add(basicRegister);
        }

        public void Dispose()
        {
            Container.Dispose();
        }

        public bool IsRegisted(Type type)
        {
            return Container.Kernel.HasComponent(type);
        }

        public bool IsRegisted<T>()
        {
            return Container.Kernel.HasComponent(typeof(T));
        }

        public void Regist(Type type, ShanYuLifeStyle lifeStyle = ShanYuLifeStyle.Singleton)
        {
            Container.Register(setLifeStyle(Component.For(type), lifeStyle));
        }

        private ComponentRegistration<T> setLifeStyle<T>(ComponentRegistration<T> componentRegistration, ShanYuLifeStyle lifeStyle)
            where T : class
        {
            switch (lifeStyle)
            {
                case ShanYuLifeStyle.Singleton:
                    return componentRegistration.LifestyleSingleton();
                case ShanYuLifeStyle.Transient:
                    return componentRegistration.LifestyleTransient();
                default:
                    return componentRegistration;
            }
        }

        public void Regist(Type type, Type implementType, ShanYuLifeStyle lifeStyle = ShanYuLifeStyle.Singleton)
        {
            Container.Register(setLifeStyle(Component.For(type, implementType).ImplementedBy(implementType), lifeStyle));
        }

        public void RegistAssembly(Assembly assembly)
        {
            Container.Install(FromAssembly.Instance(assembly));
            foreach (var item in _registList)
            {
                item.RegistAssembly(assembly, this);
            }
        }

        void IContainerRegister.Regist<T, TI>(ShanYuLifeStyle lifeStyle)
        {
            Container.Register(setLifeStyle(Component.For<T, TI>().ImplementedBy<TI>(), lifeStyle));
        }

        public T Resolver<T>()
        {
            return Container.Resolve<T>();
        }

        public T Resolver<T>(Type type)
        {
            return (T)Container.Resolve(type);
        }

        public void Realse(object obj)
        {
            Container.Release(obj);
        }

        public T Resolver<T>(object args)
        {
            return Container.Resolve<T>(args);
        }

        public void Regist<T>(ShanYuLifeStyle lifeStyle = ShanYuLifeStyle.Singleton) where T : class
        {
            Container.Register(
                setLifeStyle(Component.For<T>(), lifeStyle)
                );
        }

        private IList<IBasicRegister> _registList;
    }
}
